package com.free.lazy.manage;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Component
public class JwtTokenProvider {

    /**
     * 过期时间(单位:秒)
     */
    public static final long ACCESS_EXPIRE = 86400L; // 24小时

    /**
     * 加密算法
     */
    private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;

    /**
     * 秘钥 - 建议从配置文件中读取
     */
    private final static String SECRET = "your-256-bit-secret-key-must-be-at-least-32-chars";

    /**
     * 秘钥实例
     */
    public static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());

    /**
     * jwt签发者
     */
    private final static String JWT_ISS = "Tiam";

    /**
     * jwt主题
     */
    private final static String SUBJECT = "Peripherals";

    /**
     * 生成token - 基于 Authentication
     */
    public String generateToken(Authentication authentication) {
        String username = authentication.getName();
        List<String> roles = authentication.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());

        return generateToken(username, roles);
    }

    /**
     * 生成token - 基于用户名和角色
     */
    public String generateToken(String username, List<String> roles) {
        String uuid = UUID.randomUUID().toString();
        Date exprireDate = Date.from(Instant.now().plusSeconds(ACCESS_EXPIRE));

        return Jwts.builder()
                .header()
                .add("typ", "JWT")
                .and()
                .claim("username", username)
                .claim("roles", roles)
                .id(uuid)
                .expiration(exprireDate)
                .issuedAt(new Date())
                .subject(SUBJECT)
                .issuer(JWT_ISS)
                .signWith(KEY, ALGORITHM)
                .compact();
    }

    /**
     * 验证token
     */
    public boolean validateToken(String token) {
        try {
            Jwts.parser()
                    .verifyWith(KEY)
                    .build()
                    .parseSignedClaims(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 从token中获取用户名
     */
    public String getUsernameFromToken(String token) {
        return parsePayload(token).get("username", String.class);
    }

    /**
     * 从token中获取角色列表
     */
    public List<String> getRolesFromToken(String token) {
        return parsePayload(token).get("roles", List.class);
    }

    /**
     * 解析token
     */
    public Jws<Claims> parseClaim(String token) {
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(token);
    }

    public JwsHeader parseHeader(String token) {
        return parseClaim(token).getHeader();
    }

    public Claims parsePayload(String token) {
        return parseClaim(token).getPayload();
    }

    /**
     * 获取token过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        return parsePayload(token).getExpiration();
    }

    /**
     * 检查token是否过期
     */
    public boolean isTokenExpired(String token) {
        Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }
}